#include "camera1.h"
#include "head.h"
#include "../ui_visual2.h"

QScopedPointer<camera1> camera1::self;

camera1* camera1::getInstance()
{
    if (self.isNull()) {
        static QMutex mutex;
        QMutexLocker locker(&mutex);
        if (self.isNull()) {
            self.reset(new camera1);
        }
    }
    return self.data();
}

camera1::camera1(QObject *parent) : QThread(parent)
{
    initThread();
}

camera1::~camera1()
{
    this->stopThread();
    this->wait();
}

void camera1::initThread()
{
    stopped = false;
    localIntervals = 100;
    detectFlag = false;
    sendInfoFlag = false;
    newFrameFlag = false;
    min_score = 0.9;
    temp_count = 0;
    return;
}

void camera1::run()
{
    this->initThread();
    QTime overTime;
    try {
        while (!stopped) {
            overTime = QTime::currentTime().addMSecs(100);
            this->DoThread();
        }
    }catch (cv::Exception &e) {
        qDebug() << e.what();
    }
    while(QTime::currentTime() < overTime) {
        QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
    }
    return;
}
void camera1::stopThread()
{
    QMutexLocker locker(&mutex);
    stopped = true;
    return;
}
void camera1::setLocalIntervals(int intervals)
{
    QMutexLocker locker(&mutex);
    localIntervals = intervals;
    return;
}
void camera1::setDetectFlag(bool flag)
{
    QMutexLocker locker(&mutex);
    detectFlag = flag;
    return;
}
void camera1::setSendInfoFlag(bool flag)
{
    QMutexLocker locker(&mutex);
    sendInfoFlag = flag;
    return;
}
void camera1::setTemplateImage(QString path)
{
    QMutexLocker locker(&mutex);
    templateImage = cv::imread(path.toStdString());
    return;
}
void camera1::process()
{
    cv::Mat frameTemp;
    {
        QMutexLocker Locker(&Paras::mutexImg);
        frameTemp = Paras::image.clone();
    }
    //若frame为空，则直接返回
    if (frameTemp.empty()) {
        return;
    }
    QMutexLocker locker(&mutex);
    this->frame = frameTemp;
    newFrameFlag = true;
    return;
}
void camera1::DoThread()
{
    bool newFrameTemp, sendInfoFlagTemp;
    int mode;
    cv::Mat frameTemp;
    cv::Mat templateImageTemp;
    {
        QMutexLocker locker(&Paras::mutexMode);
        mode=Paras::Work_state;
    }
    if (mode!=3&&mode!=2) {
        //获取当前帧
        cv::Mat tempImage;
        {
            QMutexLocker Locker(&Paras::mutexCap);
            //若相机未启动则直接返回
            if(!Paras::is_cap_available)return;
            Paras::cap >> tempImage;
        }
        {
            QMutexLocker locker(&Paras::mutexImg);
            Paras::image = tempImage.clone();
        }
        frameTemp = tempImage.clone();
        {
            QMutexLocker Locker(&Paras::templateMutexMat);
            templateImageTemp = Paras::templateImage.clone();
        }
    }
    {
        QMutexLocker locker(&mutex);
        newFrameTemp = newFrameFlag;
        sendInfoFlagTemp = sendInfoFlag;
    }
    if (mode==3) {
        {
            QMutexLocker locker(&Paras::fixedframeMutexMat);
            frameTemp = Paras::fixedframe.clone();
        }
        if(frameTemp.empty()) {
            return;
        }
        cv::Point2d tempCenter;//模板中心
        int width;//模板宽度
        int height;//模板高度
        int angle;//模板角度
        {
            QMutexLocker locker(&Paras::mutexTemp);
            tempCenter = Paras::tempCenter;
            width = Paras::tempwidth;
            height = Paras::tempheight;
            angle = Paras::tempangle;
        }
        //将fixedframeTemp旋转角度angle后在其上画出模板，模板中心点为tempCenter，长宽为width和height
        cv::rectangle(frameTemp, cv::Point(tempCenter.x - width / 2, tempCenter.y - height / 2), cv::Point(tempCenter.x + width / 2, tempCenter.y + height / 2), cv::Scalar(0, 0, 255), 2);
    }
    else if (newFrameTemp) {
        if (frameTemp.empty()) {
            return;
        }
        //工作状态 0:未运行 1:运行中 2:标注模式-未运行 3:标注模式-运行中  4:标定模式-未运行 5:标定模式-运行中 6:PLC控制
        //即：0:图像无需更改 1:图中显示模板匹配结果、标出角度和位置 2:图像无需更改 3:固定图像，同时显示框选位置 4:图像无需更改 5:显示图中格点位置，并实时显示标定结果 6:图中心画出十字准星
        if (mode==1) {
            cv::Point2d centerTemp;
            double angleTemp, scaleTemp, scoreTemp;
            //TODO：加入对不同角度和scale模板的适配
            func::matchTemplate(frameTemp, templateImageTemp, cv::TM_CCOEFF_NORMED, min_score, "0", "1",centerTemp, angleTemp, scaleTemp, scoreTemp);
            if (scoreTemp > min_score) {
                center = centerTemp;
                rotateAngle = angleTemp;
                if (sendInfoFlagTemp) {
                    this->SendResult();
                }
            }
        }
        else if (mode==5) {
            //TODO：通过棋盘格标定，获取图像中的格点位置
        }
        else if (mode==6) {
            //在图frameTemp中心以图像宽度的1/10为半径画出十字准星
            cv::circle(frameTemp, cv::Point(frameTemp.cols / 2, frameTemp.rows / 2), frameTemp.cols / 10, cv::Scalar(0, 0, 255), 2);
            cv::line(frameTemp, cv::Point(frameTemp.cols / 2, frameTemp.rows / 2 - frameTemp.cols / 10), cv::Point(frameTemp.cols / 2, frameTemp.rows / 2 + frameTemp.cols / 10), cv::Scalar(0, 0, 255), 2);
            cv::line(frameTemp, cv::Point(frameTemp.cols / 2 - frameTemp.cols / 10, frameTemp.rows / 2), cv::Point(frameTemp.cols / 2 + frameTemp.cols / 10, frameTemp.rows / 2), cv::Scalar(0, 0, 255), 2);
        }
    }
    {
        QMutexLocker locker(&mutex);
        newFrameFlag = false;
    }
    {
        QMutexLocker locker(&Paras::mutexImageShow);
        Paras::imageShow = frameTemp.clone();
    }
    emit sendImage();
    return;
}

void camera1::SendResult()
{
    emit sendPos(center, rotateAngle);
    return;
}